package org.BiteTheDice;
import java.util.ArrayList;
import java.util.Iterator;

import android.app.AlertDialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;

public class ColorAlertDialog extends AlertDialog {
	private static int NONE = -1;
	private int tint = NONE;

	/**
	 * @param context
	 * @param theme
	 */
	protected ColorAlertDialog(Context context) {
		super(context);
		init();
	}

	/**
	 * @param context
	 * @param theme
	 */
	protected ColorAlertDialog(Context context, int theme) {
		super(context, theme);
		init();
	}
	
	/**
	 * 
	 */
	private void init() {      
		final Theme theme = getContext().getTheme();
		final TypedArray attrs = theme.obtainStyledAttributes(new int[] { android.R.attr.tint });
		tint = attrs.getColor(0, NONE);
	}

	/* (non-Javadoc)
	 * @see android.app.Dialog#show()
	 */
	@Override
	public void show() {
		super.show();
		setTint(tint);
	}

	/**
	 * @param tint
	 */
	public void setTint(int tint) {
		this.tint = tint;

		if ( tint != NONE ) {
			Iterator<View> vi = iterator(android.R.id.content);
			while ( vi.hasNext() ) {
				tintView(vi.next(), tint);
			}
		}
	}

	/**
	 * Set the {@link tint} color for the {@link View}
	 * 
	 * @param v the {@link View} to change the tint
	 * @param tint color tint
	 */
	private static void tintView(final View v, final int tint) {
		if ( v != null ) {
			final Mode mode = Mode.SRC_ATOP;
			if ( v instanceof ImageView ) {
				final Drawable d = ((ImageView)v).getDrawable();
				if ( d != null ) {
					try {
						d.mutate().setColorFilter(tint, mode);
					} catch (Exception ex) {
						// Patch for Android 1.5
					}
				}
			}
			else {
				final Drawable d = v.getBackground();
				if ( d != null ) {
					d.setColorFilter(tint, mode);
				}
			}
		}
	}

	/**
	 * @param button
	 */
	public void setCancelButton(Button button) {
		button.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				cancel();
			}
		});
	}

	/**
	 * @param button
	 */
	public void setPositiveButton(Button button) { 
		button.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				dismiss();  
			}
		});
	}

	/**
	 * Return a {@link ChildrenIterator} starting at the {@link ViewGroup}
	 * identified by the specified resource id.
	 *  
	 * @param res resource id of the {@link ViewGroup} to start the iteration
	 * @return iterator
	 */
	public Iterator<View> iterator(int res) {
		final ViewGroup vg = (ViewGroup)findViewById(res);
		return new ChildrenIterator<View>(vg);
	}

	public static class Builder extends AlertDialog.Builder{
		private ColorAlertDialog dialog;

		public Builder(Context context) {
			super(context);
			dialog = new ColorAlertDialog(context);
		}

		public Builder(Context context, int theme) {
			super(context);
			dialog = new ColorAlertDialog(context, theme);
		}
		
		@Override
		public ColorAlertDialog create() {
			return dialog;
		}
				
		@Override
		public Builder setMessage(CharSequence message) {
			dialog.setMessage(message);
			return this;
		}
		
		@Override
		public Builder setTitle(CharSequence title) {
			dialog.setTitle(title);
			return this;
		}
		@Override
		public Builder setPositiveButton(int resId, OnClickListener listener) {
			return setPositiveButton(dialog.getContext().getString(resId), listener);
		}
		@Override
		public Builder setPositiveButton(CharSequence text, OnClickListener listener) {
			dialog.setButton(BUTTON_POSITIVE, text, listener);
			return this;
		}
		@Override
		public Builder setNegativeButton(int resId, OnClickListener listener) {
			return setNegativeButton(dialog.getContext().getString(resId), listener);
		}
		@Override
		public Builder setNegativeButton(CharSequence text, OnClickListener listener) {
			dialog.setButton(BUTTON_NEGATIVE, text, listener);
			return this;
		}
		@Override
		public Builder setIcon(int iconId) {
			dialog.setIcon(iconId);
			return this;
		}
		@Override
		public Builder setCancelable(boolean flag) {
			dialog.setCancelable(flag);
			return this;   
		}
		@Override
		public ColorAlertDialog show() {
			dialog.show();
			return dialog;
		}
	}

	public class ChildrenIterator<V extends View> implements Iterator<V>{
		
		ArrayList<V> list;
		private int i;

		public ChildrenIterator(ViewGroup vg) {
			super();

			if ( vg == null ) 
				throw new RuntimeException("ChildrenIterator needs a ViewGroup != null to find its children");

			init();
			findChildrenAndAddToList(vg, list);
		}

		private void init() {
			list = new ArrayList<V>();
			i = 0;         
		}
		
		public boolean hasNext() {
			return ( i < list.size() );
		}

		public V next() {
			return list.get(i++);
		}

		public void remove() {
			list.remove(i);
		}

		@SuppressWarnings("unchecked")
		private void findChildrenAndAddToList(final ViewGroup root, final ArrayList<V> list){
			for (int i=0; i < root.getChildCount(); i++) {
				V v = (V)root.getChildAt(i);
				list.add(v);
				if ( v instanceof ViewGroup ) 
					findChildrenAndAddToList((ViewGroup)v, list);

			}       
		}
	} 
}